---
id: httpclient
title: 创建HttpClient
---

import CardLink from "@site/src/components/CardLink.js";
import BilibiliCard from '@site/src/components/BilibiliCard.js';

### 定义

命名空间：TouchSocket.Http <br/>
程序集：[TouchSocket.Http.dll](https://www.nuget.org/packages/TouchSocket.Http)

## 一、说明

HttpClient是Http客户端类。主要用于请求Http报文。与.net的HttpClient不同的是，此处的HttpClient，是基于单个连接的客户端，且有明显的连接、断开连接等动作。


## 二、可配置项

继承TcpClient

<a name="mMhq1"></a>

## 三、支持插件接口

支持**ITcpPlugin**接口。

<a name="LAsiE"></a>

## 四、创建HttpClient

### 4.1 创建常规HttpClient
```csharp showLineNumbers
var client = new HttpClient();
await client.ConnectAsync("http://localhost:7219");//先做连接
```

<BilibiliCard title="创建HttpClient并完成请求" link="https://www.bilibili.com/cheese/play/ep1688271" isPro="true"/>

### 4.2 创建Ssl的HttpClient（Https）

```csharp showLineNumbers
var client = new HttpClient();
await client.ConnectAsync("https://localhost:7219");//先做连接
```

如果是自定义证书，则需要手动加载证书

```csharp showLineNumbers
var client = new HttpClient();

var config = new TouchSocketConfig();
config.SetRemoteIPHost("https://localhost:7219")
    .SetClientSslOption(new ClientSslOption()
    {
        ClientCertificates = new X509CertificateCollection() { new X509Certificate2("Socket.pfx", "Socket") },
        SslProtocols = SslProtocols.Tls12,
        TargetHost = "localhost",
        CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true; }
    }); ;

//配置config
await client.SetupAsync(config);
await client.ConnectAsync();//先做连接
```

<BilibiliCard title="创建Https客户端" link="https://www.bilibili.com/cheese/play/ep1688272" isPro="true"/>

:::info 备注

实际上直接使用`ConnectAsync("https://localhost:7219")`的方式是合并了`SetupAsync`与`ConnectAsync`。所以当需要额外配置时，应当遵循所有配置都在`TouchSocketConfig`的约定。这样代码也比较简单明了。

:::  

## 五、发送请求

因为我的HttpClient是面向连接的，所以，在请求时，请求url只需要填写host之后的部分即可（即路由部分）。

### 5.1 发起Get请求到字符串

```csharp showLineNumbers
//直接发起一个Get请求，然后返回Body字符串。
var body = await client.GetStringAsync("/WeatherForecast");
```

### 5.2 发起Get请求到字节数组

```csharp showLineNumbers
//直接发起一个Get请求，然后返回Body数组。
var bodyBytes = await client.GetByteArrayAsync("/WeatherForecast");
```

### 5.3 发起Get请求到流数据

```csharp showLineNumbers
//直接发起一个Get请求文件，然后写入到流中。
using (var stream=File.Create("1.txt"))
{
    await client.GetFileAsync("/WeatherForecast",stream);
}
```

<BilibiliCard title="自定义Query和Header参数" link="https://www.bilibili.com/cheese/play/ep1688274" isPro="true"/>

### 5.4 构建自定义请求

```csharp showLineNumbers
//创建一个请求
var request = new HttpRequest();
request.InitHeaders()
    .SetUrl("/WeatherForecast")
    .SetHost(client.RemoteIPHost.Host)
    .AsGet();


using (var responseResult = await client.RequestAsync(request, 1000 * 10))
{
    var response = responseResult.Response;
    Console.WriteLine(await response.GetBodyAsync());//将接收的数据，一次性转为utf8编码的字符串
}
```

### 5.5 构建自定义请求，持续读取大数据

```csharp showLineNumbers
//创建一个请求
var request = new HttpRequest();
request.InitHeaders()
    .SetUrl("/WeatherForecast")
    .SetHost(client.RemoteIPHost.Host)
    .AsGet();


using (var responseResult = await client.RequestAsync(request, 1000 * 10))
{
    var response = responseResult.Response;

    while (true)
    {
        using (var blockResult = await response.ReadAsync())
        {
            //每次读到的数据
            var memory = blockResult.Memory;
            Console.WriteLine(memory.Length);

            if (blockResult.IsCompleted)
            {
                //数据读完成
                break;
            }
        }
    }
}
```

### 5.6 构建自定义Post请求，持续写入流

```csharp {5} showLineNumbers
using (var stream=File.OpenRead("TouchSocket.dll"))
{
    //创建一个请求
    var request = new HttpRequest();
    request.SetContent(new StreamHttpContent(stream));//设置流内容
    request.InitHeaders()
        .SetUrl("/bigwrite")
        .SetHost(client.RemoteIPHost.Host)
        .AsPost();

    using (var responseResult = await client.RequestAsync(request, 1000 * 10))
    {
        var response = responseResult.Response;
    }
    Console.WriteLine("完成");
}
```

<BilibiliCard title="使用SSE实现类似AI问答效果" link="https://www.bilibili.com/cheese/play/ep1688275" isPro="true"/>

:::tip 提示

在构建自定义请求时，如果使用`AsGet`、`AsPost`等方法可以直接设置当前请求为`Get`、`Post`等。如果没有扩展方法可以使用时，可以使用`AsMethod`来实现，例如：`AsMethod("GET")`。

:::  

## 六、传输文件

### 6.1 下载文件

```csharp {4} showLineNumbers
//直接发起一个Get请求，然后写入到流中。
using (var stream=File.Create("1.txt"))
{
    await client.GetFileAsync("/WeatherForecast",stream);
}
```

### 6.2 上传文件

```csharp showLineNumbers
await client.UploadFileAsync("/upfile", new FileInfo("filePath"));
```

## 七、本文示例Demo

<CardLink link="https://gitee.com/RRQM_Home/TouchSocket/tree/master/examples/Http/HttpClientConsoleApp"/>